home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / UTIL / Alpha 6.5.sit / Tcl / SystemCode / procs.tcl < prev    next >
Text File  |  1996-08-15  |  31KB  |  1,235 lines

  1.  
  2. #==============================================================================
  3. # Load electric alias, rebind tcl file completion for precedence.
  4. proc loadElectricAlias {} {
  5.     global HOME
  6.     uplevel #0 {
  7.         source "$HOME:Tcl:ElectricAlias:electricAlias.tcl"
  8.     }
  9.     message "ElectricAlias loaded."
  10.     bind '¥t' tclFileCompletion "Shel"
  11.     enableMenuItem -m install "Electric Alias" off
  12. }
  13.  
  14. proc debug {} {
  15.     uplevel #0 {
  16.         set debugging 1
  17.     }
  18. }
  19.  
  20.  
  21. proc normalLeftBracket {} {
  22.     insertText "¥{"
  23. }
  24. proc normalRightBracket {} {
  25.     insertText "¥}"
  26. }
  27. bind '¥[' <zs>  normalLeftBracket
  28. bind '¥]' <zs>  normalRightBracket
  29.             
  30. # Select the next or current word. If word already selected, will go to next.
  31. proc hiliteWord {} {
  32.     if {[getPos]!=[selEnd]}    forwardChar
  33.     forwardWord
  34.     set start [getPos]
  35.     backwardWord
  36.     select $start [getPos]
  37. }
  38. bind 'h' <z> hiliteWord
  39.  
  40. #================================================================================
  41. # Mode variables
  42. #================================================================================
  43. # For mark stack.
  44. set markName 0
  45. set markStack ""
  46.  
  47. # mapping of windows to current modes.
  48. set winModes("") ""
  49.  
  50. # making vars local to windows
  51. # 'incomingVars' used to hold old var values that have been overwritten in current window
  52.  
  53. #================================================================================
  54. # Handle 'flag' and 'var' menu selections.
  55. #================================================================================
  56. # proc editFlag {menu item} {
  57. #     global $item incomingVars localVars modifiedVars tcl_var_procs
  58. #     if {[regexp {¥? (.*)} $item dummy var]} {
  59. #         alphaHelp
  60. #         eval select [search -f 1 -r 1 "^$var"]
  61. #         return
  62. #     }
  63. #     lappend modifiedVars $item
  64. #     set val [expr ([set $item]-1)*-1]
  65. #     markMenuItem $menu $item [expr ($val)?"on":"off"]
  66. #     set $item $val
  67. #     if {[info exists tcl_var_procs($item)]} {
  68. #         $tcl_var_procs($item) $item
  69. #     }
  70. # }
  71.  
  72. proc editVar {menu item} {
  73.     global $item incomingVars localVars modifiedVars
  74.  
  75.     if {[regexp {¥? (.*)} $item dummy var]} {
  76.         alphaHelp
  77.         eval select [search -f 1 -r 1 "^$var"]
  78.         return
  79.     }
  80.     lappend modifiedVars $item
  81.     append prmpt "New Value of " $item ": "
  82.     if ![catch {prompt $prmpt [set $item]} res] {
  83.         set $item $res
  84.     }
  85. }
  86.  
  87.  
  88.  
  89.  
  90. #================================================================================
  91.  
  92. # Instantiate a global variable to the path of a file (usually an app). As a
  93. # side-effect, make the instantiation permanent.
  94. proc addAppPath {name var} {
  95.     global $var modifiedVars
  96.     
  97.     if {$name == "CodeWarrior Compiler"} {
  98.         alertnote {Please locate the compiler via menu item "Config:App Paths:CodeWarrior Compiler"}
  99.         error ""
  100.     } elseif {$name == "CodeWarrior Debugger"} {
  101.         alertnote {Please locate the debugger via menu item "Config:App Paths:CodeWarrior Debugger"}
  102.         error ""
  103.     }
  104.         
  105.     set $var [getfile "Find '$name' app:"]
  106.     lappend modifiedVars $var
  107. }
  108.  
  109.  
  110. proc getFileSig {f} {
  111.     getFileInfo $f arr
  112.     return $arr(creator)
  113. }
  114.  
  115. proc getFileType {f} {
  116.     getFileInfo $f arr
  117.     return $arr(type)
  118. }
  119.  
  120.  
  121. # Look for given app sig in active processes. If not there, try to 
  122. # launch with 'path' prompting for 'path' if necessary.
  123. # Return the real name of the app. Don't switch.
  124.  
  125. # Slightly modified version of 'checkRunning' that looks for any of a
  126. # list of running apps.  The name of the app is returned. 
  127. proc checkRunning {prompt sigs path {in_front 1}} {
  128.     global $path
  129.  
  130.     # See if a process w/ any of the acceptable sigs already running.
  131.     # If so, use it, whether it's the one specified by $path or not.
  132.     #
  133.     foreach proc [processes] {
  134.         # if a running app has the correct sig, ...
  135.         if {[lsearch -exact $sigs [lindex $proc 1]] >= 0} {
  136.             # ...then return its name.
  137.             return [lindex $proc 0]
  138.         }
  139.     }
  140.  
  141.     # If the path variable or the file it references don't exist,
  142.     # or if its sig isn't one that we expect, then prompt the user 
  143.     # to locate the app.
  144.     #
  145.     if {![info exists $path] || ![file exists [set $path]] 
  146.              || [lsearch -exact $sigs [getFileSig [set $path]]] < 0} {
  147.         if {[catch {addAppPath $prompt $path}]} return
  148.     }
  149.  
  150.     # Check that the user's choice has an acceptable sig
  151.     if {[lsearch -exact $sigs [getFileSig [set $path]]] < 0} {
  152.         unset $path
  153.         message "Inappropriate file chosen"
  154.         return {} 
  155.     }
  156.     
  157.     # Launch the app
  158.     if {$in_front} {
  159.         if {[catch {launch -f [set $path]}]} {
  160.             error "Problem with launching file (out of memory?)"
  161.         }
  162.     } else {
  163.         if {[catch {launch [set $path]}]} {
  164.             error "Problem with launching file (out of memory?)"
  165.         }
  166.     }        
  167.     
  168.     # Return the name of the chosen application
  169.     return [file tail [set $path]]
  170. }
  171.  
  172.  
  173. #===============================================================================
  174.  
  175. # Switch to 'sig', launching if necesary
  176. proc launchForeAppl {sig} {
  177.     set name [nameFromAppl $sig]
  178.     if {[catch {switchTo "'$sig'"}]} {
  179.         launch -f $name
  180.     }        
  181.     return $name
  182. }
  183.  
  184. # Ensure that the app is at least running in the background.
  185. proc launchBackAppl {sig} {
  186.     set name [nameFromAppl $sig]
  187.     launch $name
  188.     return $name
  189. }
  190.  
  191. # Check to see if any of the 'sigs' is running. If so, return its name.
  192. # Otherwise, attempt to launch the file named by 'sig'.
  193. proc launchBackApplSigs    {sigs sig {prompt "Please locate the application:"}} {
  194.     global $sig    modifiedVars
  195.     foreach    p [processes] {
  196.         if { [set ind [lsearch -exact $sigs [lindex $p 1]]] >= 0 } {
  197.             set s [lindex $sigs $ind]
  198.             if { ![info exists $sig] || ($s != [set    $sig]) } {
  199.                 set    $sig $s
  200.                 lappend    modifiedVars $sig
  201.             }
  202.             return [nameFromAppl $s]
  203.         }
  204.     }
  205.     if {![info exists $sig] || ([set $sig] == "")}    {
  206.         set    $sig [getFileSig [getfile $prompt]]
  207.         lappend    modifiedVars $sig
  208.     }
  209.     return [launchBackAppl [set    $sig]]
  210. }
  211.  
  212. proc getApplSig {prompt sig} {
  213.     global $sig modifiedVars
  214.     if {[catch {nameFromAppl [set $sig]}]} {
  215.         set $sig [getFileSig [getfile $prompt]]
  216.         lappend modifiedVars $sig
  217.     }
  218. }
  219.  
  220. #================================================================================
  221. # Excalibur is the only Mac spell-checker that I know of which will handle LaTeX as
  222. # well as ordinary text.
  223.  
  224.  
  225. proc spellcheckWindow {} {
  226.     global resumeRevert
  227.  
  228.     set name [launchForeAppl XCLB]
  229.  
  230.     if {[winDirty]} {
  231.         if {[askyesno "Save '[lindex [winNames] 0]'?"] == "yes"} {
  232.             save
  233.         }
  234.     }
  235.     sendOpenEvent noReply [file tail $name] [car [winNames -f]]
  236.     set resumeRevert 1
  237. }
  238.  
  239. proc spellcheckSelection {} {
  240.     global excaliburPath 
  241.  
  242.     catch {checkRunning Excalibur XCLB excaliburPath} name
  243.  
  244.     if {[getPos] == [selEnd]} {
  245.         beep
  246.         message "No selection"
  247.         return;
  248.     }
  249.     copy
  250.     switchTo $name
  251. }
  252.  
  253. #================================================================================
  254.  
  255.  
  256. proc alphaHelp {} {
  257.     global HOME alphaLite
  258.     if $alphaLite {
  259.         edit -r "$HOME:Help:Quick Start"
  260.     } else {
  261.         edit -r "$HOME:Help:Manual"
  262.     }
  263. }
  264.  
  265.  
  266. proc tclHelp {} {
  267.     global HOME
  268.     edit -r "$HOME:Help:Tcl Commands"
  269. }
  270.  
  271.  
  272. proc dividingLine {} {
  273.     insertText "===============================================================================¥r"
  274. }
  275. bind 'l' <C> dividingLine
  276.  
  277. proc texDividingLine {} {
  278.     insertText "%===============================================================================¥r"
  279. }
  280. bind 'l' <C> texDividingLine TeX
  281.  
  282. proc cDividingLine {} {
  283.     insertText "//===============================================================================¥r"
  284. }
  285. bind 'l' <C> cDividingLine C
  286. bind 'l' <C> cDividingLine C++
  287.  
  288. proc tclDividingLine {} {
  289.     insertText "#===============================================================================¥r"
  290. }
  291. bind 'l' <C> tclDividingLine Tcl
  292.  
  293.  
  294. #================================================================================
  295.  
  296. if {![string length [info commands oldCd]]} {
  297.     rename cd oldCd
  298. }
  299.  
  300. proc cd args {
  301.     global HOME
  302.     if {[llength $args]} {
  303.         oldCd [string trim [eval list $args] "        ¥{¥}"]
  304.     } else {
  305.         oldCd $HOME
  306.     }
  307. }
  308.  
  309.  
  310.  
  311. #############################################################################
  312. #  List the name and value of each element of the array $arrName.
  313. #  (Convenient to use as a shell command.)
  314. #
  315. #  Note: it's slower to insert the lines one-by-one like this, but 
  316. #  assembling everything in $lines before inserting can seriously crash Alpha
  317. #  if the result is too big.  (Trying to list the contents of $auto_index()
  318. #  will do it.)  This method seems to be more robust.
  319. #
  320. proc listArray {arrName} {
  321.     global $arrName
  322.     set lines {}
  323.     if {![catch {info vars $arrName}]} {
  324.         foreach nm [lsort -ignore [array names $arrName]] {
  325.             append lines [format "¥r%-20s ¥"%s¥"" $nm [set ${arrName}($nm)]]
  326.         }
  327.         insertText $lines
  328.     } else {
  329.         alertnote "¥"$arrName¥" doesn't exist in this context"
  330.     }
  331. }
  332.  
  333.  
  334.  
  335. #================================================================================
  336.     
  337. proc selectParagraph {} {
  338.     set pos [getPos]
  339.     set start [paraStart $pos] 
  340.     set finish [paraFinish $pos]
  341.     goto $start
  342.     select $start $finish
  343. }
  344.  
  345. # wrapText ==  getText ; breakIntoLines ; replaceText
  346. # Remove text from window, transform (join, del-ws), insert back into window.
  347. proc fillTextByPar {from to} {
  348.     set text [getText $from $to]
  349.     regsub -all "¥r(¥[ ¥t¥]*¥r)+" $text "¥r¥r¥r" text
  350.     regsub -all "(¥[^¥r¥])¥r" $text "¥¥1 " text
  351.     regsub -all "¥[ ¥t¥]+" $text " " text
  352.     return [breakIntoLines $text]
  353. }
  354.  
  355. proc fillRegionByPar {{start -1} {finish -1}} {
  356. #    # if {[getPos] == [selEnd]} { return}
  357.     if {($start < 0) || ($finish < 0)} {
  358.         set start [lineStart [getPos]]
  359.         set finish [selEnd] }
  360.     if {$start >= $finish} return
  361.     goto $start
  362.     set text [fillTextByPar $start $finish]
  363.     replaceText $start $finish $text "¥r"
  364. }
  365.     
  366. #
  367. # join Lines in region -- if no optional args, use selection
  368. #
  369. proc joinRegion {{from -1} {to -1}} {
  370.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  371.     if {$from >= $to} return
  372.     set text [getText $from $to]
  373.     regsub -all "¥r(¥[ ¥t¥]*¥r)+" $text "¥r¥r¥r" text
  374.     regsub -all "(¥[^¥r¥])¥r" $text "¥¥1 " text
  375.     replaceText $from $to $text "¥r"
  376. }
  377. # WARNING:    regsub ^$ refers to string endpts (not lines)
  378. # FUTURE:    filterLines like perl:
  379. #    replaceText[apply_to_all(cmd,split [getText [getPos] [selEnd]] "¥r")]
  380. # OR:    replaceInRegion: dup_¥r, $=>¥r ??
  381. #
  382.  
  383.  
  384. #
  385. # Remove text from window, transform (delete dup ws), insert back into window.
  386. #
  387. # inputs: message, alertnote, askyesno, listpick, prompt KILLS SELECTION.
  388. # search: bnds = search -forward -regExpr -ignoreCase -matchWords -noabort 
  389. #        -l limit pat pos
  390. proc regsubInRegion {from to srch repl} {
  391.     if {![string length $srch]} return
  392.     if {$from >= $to} return
  393.     set text [getText $from $to]
  394.     regsub -all "$srch" $text "$repl" text
  395.     replaceText $from $to $text
  396. }
  397. #    while {($pos < $to) &&
  398. #          ![catch {search -s -f 1 -r 1 -i 1 -m 0 "$srch" $pos} mtch]} {
  399. #        set mbeg [lindex $mtch 0]
  400. #        set pos [lindex $mtch 1]
  401. #        replaceText $mbeg $pos $repl }
  402.  
  403. #proc backSlashSub {arg} { eval [concat return "¥"$arg¥""] }
  404.  
  405. proc backSlashSub {arg} {
  406.     regsub -all {¥¥} $arg {¥¥¥¥} arg
  407.     regsub -all {¥[} $arg {¥¥[} arg
  408.     regsub -all {¥]} $arg {¥¥]} arg
  409.     eval [concat return "¥"$arg¥""]
  410. }
  411.  
  412. proc replaceInRegion {} {
  413.     if [catch {prompt "Search RegExpr:" ""} srch] return
  414.     if [catch {prompt "Replace String:" ""} repl] return
  415.     if {![string length $srch]} return
  416.     regsubInRegion [getPos] [selEnd] ¥
  417.         [backSlashSub "$srch"] [backSlashSub "$repl"]
  418. }
  419.  
  420. #
  421. # Apply command to each line (or paragraph) in selection ;
  422. #    if no cmd arg then prompts for it
  423. #
  424. proc filterLines {{cmd 0} {parunit 0}} {
  425.     if {$cmd == 0} {
  426.       if {[catch { prompt "Line-filter command: " "" } cmd]} { return } }
  427.     if {![string length $cmd]} return
  428.     set unitStart lineStart
  429.     set unitEnd nextLineStart
  430.     if {$parunit} {
  431.         set unitStart paraStart
  432.         set unitEnd paraFinish }
  433.     set pos [$unitStart [getPos]]
  434.     set finish [selEnd]
  435.     if {$pos >= $finish} return
  436.     goto $pos
  437.     createTMark "filterLend" $finish
  438.     set next [$unitEnd $pos]
  439.     while {(($next > $pos) && ($pos < $finish))} {
  440.         goto [expr $next-1]
  441.         createTMark "filterLnext" $next
  442.         setMark
  443.         goto $pos
  444.         markHilite
  445.         if {[catch [list uplevel #0 "$cmd"] retval]} {
  446.             select $pos $finish
  447.             alertnote $retval
  448.             return
  449.         }
  450.         if {$next==$finish} break
  451.         set ind [lsearch -regexp [lindex [getTMarks] 0] "filterLend.*"]
  452.         set finish [lindex [lindex [lindex [getTMarks] 0] $ind] 2]
  453.         gotoTMark "filterLnext"
  454.         set pos [$unitStart [getPos]]
  455.         set next [$unitEnd $pos]
  456.     }
  457.     removeTMark "filterLend"
  458.     removeTMark "filterLnext"
  459. }
  460.  
  461.  
  462. proc filterParagraphs {{cmd 0}} { filterLines $cmd 1 }
  463.  
  464. # WARNING: deselecting sets the mark to selEnd
  465. proc sortParagraphs {{from -1} {to -1}} {
  466.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  467.     if {$from >= $to} return
  468.     joinRegion {$from $to}
  469.     select [getPos] [nextLineStart [getMark]]
  470.     sortLines
  471.     select [getPos] [getPos]
  472.     regsubInRegion [getPos] [getMark] "¥r" "¥r¥r" 
  473.     wrapRegion
  474. }
  475.  
  476. #
  477. # Sample
  478. #
  479. proc filterRegion {{from -1} {to -1} {cmd 0} {newwin 0}} {
  480.     if {$cmd == 0} {
  481.       if {[catch { prompt "Eval command: " "" } cmd]} { return }
  482.     }
  483.     if {![string length $cmd]} return
  484.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  485.     if {$from >= $to} return
  486.     set pos [getPos]
  487.     set text [getText $from $to]
  488.     set text [$cmd $text]
  489.     replaceText $from $to $text "¥r"
  490.     goto $pos
  491. }
  492.  
  493.  
  494. #
  495. set lastEvaled ""
  496. proc evaluate {} {
  497.     global lastEvaled
  498.     if {[string length $lastEvaled]} {
  499.         set p "M-x ($lastEvaled): "
  500.     } else {
  501.         set p "M-x: "
  502.     }
  503.     if {[catch {statusPrompt $p} text]} {return}
  504.     if {![string length $text]} {set text $lastEvaled}
  505.     $text
  506.     set lastEvaled $text
  507. }
  508.  
  509.  
  510. # First, define macros to bypass the electric braces.
  511. proc ordLeftBrace {} {
  512.     insertText "        ¥{"
  513. }
  514. bind {'['} <cs> ordLeftBrace
  515.  
  516. proc ordRightBrace {} {
  517.     insertText "¥}"
  518.     blink [matchIt "¥}" [expr [getPos]-1]]
  519. }
  520. bind {']'} <cs> ordRightBrace
  521.     
  522. proc quoteWord {} {
  523.     backwardWord
  524.     insertText "'"
  525.     forwardWord
  526.     insertText "'"
  527. }
  528. bind ''' <z> quoteWord
  529.  
  530. #================================================================================
  531.  
  532. proc tomac {fname} {
  533.     set fd [open $fname "r"]
  534.     set text [read $fd]
  535.     close $fd
  536.     set fd [open $fname "w"]
  537.     regsub "¥n" $text "¥r" text
  538.     puts -nonewline $fd $text
  539.     close $fd
  540. }
  541.  
  542. proc tounix {fname} {
  543.     set fd [open $fname "r"]
  544.     set text [read $fd]
  545.     close $fd
  546.     set fd [open $fname "w"]
  547.     regsub "¥r" $text "¥n" text
  548.     puts -nonewline $fd $text
  549.     close $fd
  550. }
  551.  
  552.  
  553. proc cat args {
  554.     set files ""
  555.     foreach a $args {
  556.         foreach f [glob $a] {
  557.             lappend files $f
  558.         }
  559.     }
  560.     foreach f $files {
  561.         append text "==============<$f>==============¥r"
  562.         set fd [open $f "r"]
  563.         append text "[read $fd]¥r¥r"
  564.         close $fd
  565.     }
  566.     return $text
  567. }
  568.  
  569. proc catto args {
  570.     set len [llength $args]
  571.     set to [lindex $args [expr $len -1]]
  572.     set args [lrange $args 0 [expr $len -2]]
  573.  
  574.     set files ""
  575.     foreach a $args {
  576.         foreach f [glob $a] {
  577.             lappend files $f
  578.         }
  579.     }
  580.     foreach f $files {
  581.         append text "==============<$f>==============¥r"
  582.         set fd [open $f "r"]
  583.         append text "[read $fd]¥r¥r"
  584.         close $fd
  585.     }
  586.  
  587.     set dfile $to
  588.     if {[file exists $dfile]} {
  589.         set fid [open $dfile "a"]
  590.     } else {
  591.         set fid [open $dfile "w"]
  592.     }
  593.     puts $fid $text
  594.     close $fid
  595. }
  596.  
  597.  
  598. ##############################################################################
  599. #  To be used in the windows created by "matchingLines" or by batch searches.
  600. #
  601. #  With the cursor positioned in a line corrsponding to a match, 
  602. #  go back and select the line in the original file that 
  603. #  generated this match.  (Like emacs 'Occur' functionality)
  604. #
  605. proc gotoMatch {} {
  606.     if {[string match "*MAILBOX*" [lindex [winNames] 0]]} {
  607.         mailGotoMatch
  608.         return
  609.     }
  610.     global tileHeight tileWidth tileTop tileLeft tileHeight errorHeight errorDisp tileMargin
  611.     set errorDisp [expr (2 * ($tileHeight - $tileMargin)) / 3]
  612.     set text [getText [lineStart [getPos]] [expr [nextLineStart [getPos]] - 1]]
  613.     set ind1 [string first "ー" $text]
  614.     set ind2 [string last "ー" $text]
  615.     if {$ind1 == $ind2} {
  616.         set fname [string trim [string range $text $ind1 end] {ー}]
  617.         set msg ""
  618.     } else {
  619.         set fname [string trim [string range $text $ind1 $ind2] {ー}]
  620.         set msg [string trim [string range $text $ind2 end] {ー}]
  621.     }
  622.     
  623.     set top $tileTop
  624.     set geo [getGeometry]
  625.     if {([lindex $geo 0] != $tileLeft) || ([lindex $geo 1] != $top) || ([lindex $geo 3] != $errorHeight) } {
  626.         moveWin $tileLeft $top
  627.         sizeWin $tileWidth $errorHeight
  628.     }
  629.     set mar $tileMargin
  630.     incr top [expr $errorHeight + $mar]
  631.     if {[expr {[lsearch [winNames -f] "*$fname"] >= 0}]} {
  632.         if {[string match ":*" $fname]} {
  633.             set fname [file tail $fname]
  634.         }
  635.         bringToFront $fname
  636.         set geo [getGeometry]
  637.         if {([lindex $geo 0] != $tileLeft) || ([lindex $geo 1] != $top) || ([lindex $geo 2] != $tileWidth) || ([lindex $geo 3] != $errorDisp) } {
  638.             sizeWin $tileWidth $errorDisp
  639.             moveWin $tileLeft $top
  640.         }
  641.     } elseif {[file exists $fname]} {
  642.         edit -g $tileLeft $top $tileWidth $errorDisp $fname
  643.     } else {
  644.         if {![string match "*Link*" [getText 0 [nextLineStart 0]]]} {
  645.             alertnote "File ¥" $fname ¥" not found." 
  646.         }
  647.         return
  648.     }
  649.     if {[regexp {Line ([0-9]+):} $text dummy line]} {
  650.         set pos [rowColToPos $line 0]
  651.         select $pos [nextLineStart $pos]
  652.     }
  653.     message $msg
  654. }
  655. bind 'c' <Cz>        gotoMatch
  656.  
  657.  
  658. #================================================================================
  659.  
  660. proc prevIntro {} {
  661.     set res [search -s -f 0 -r 0 {== } [getPos]]
  662.     display [lineStart [expr [lineStart [lindex $res 0]] - 1]]
  663. }
  664.  
  665. proc nextIntro {} {
  666.     set res [search -s -f 1 -r 0 {== } [getPos]]
  667.     set res [lindex $res 1]
  668.     set res [search -s -f 1 -r 0 {== } $res]
  669.     display [lineStart [expr [lineStart [lindex $res 0]] - 1]]
  670. }
  671.  
  672. #================================================================================
  673.  
  674. proc searchStart {} {
  675.     global search_start
  676.     select [getPos]
  677.     setMark
  678.     if {[catch {goto $search_start}]} {message "No previous search"}
  679. }
  680.  
  681. #================================================================================
  682.  
  683.  
  684. proc listBindings {} {
  685.     new -n {* Key Bindings *}
  686.     insertText [bindingList]
  687.  
  688.     goto 0
  689.     setWinInfo dirty 0
  690.     setWinInfo read-only 1
  691. }
  692.  
  693.  
  694. proc listFunctions {} {
  695.     global winModes
  696.     new -n {* Functions *}
  697.     insertText "===¥r¥tCommand-double-click on a function to see its definition¥r===¥r¥r" [join [lsort -ignore [info commands]] "¥r"] "¥r"
  698.     goto 0
  699.     setWinInfo dirty 0
  700.     changeMode [set winModes([lindex [winNames] 0]) Tcl]
  701. }
  702.  
  703.  
  704. #================================================================================
  705.  
  706. proc printArray {arr} {
  707.     global $arr
  708.         foreach n [array names $arr] {
  709.         append text "$n '[set ${arr}($n)]'¥r"
  710.     }
  711.     return [string trim $text "¥r"]
  712. }
  713.  
  714. #================================================================================
  715.  
  716. #================================================================================
  717.  
  718. proc sPrompt {msg def} {
  719.     global useStatusBar
  720.     if {!$useStatusBar} {return [prompt $msg $def]}
  721.     if {[catch {statusPrompt "$msg ($def): "} ans]} {
  722.         error "cancel"
  723.     }
  724.     if {![string length $ans]} {return $def}
  725.     return $ans
  726. }
  727.  
  728.  
  729. proc choicesProc {curr c} {
  730.     global choiceList
  731.     if {$c != "¥t"} {return $c}
  732.     
  733.     set matches {}
  734.     foreach w $choiceList {
  735.         if {[string match "$curr*" $w]} {
  736.             lappend matches $w
  737.         }
  738.     }
  739.     if {![llength $matches]} {
  740.         beep
  741.     } else {
  742.         return [string range [largestPrefix $matches] [string length $curr] end]
  743.     }
  744.     return ""
  745. }
  746.  
  747.  
  748. proc sPromptChoices {msg def choiceListIn} {
  749.     global useStatusBar choiceList
  750.     set choiceList $choiceListIn
  751.     if {[catch {statusPrompt -f "$msg ($def): " choicesProc} ans]} {
  752.         error "cancel"
  753.     }
  754.     if {![string length $ans]} {return $def}
  755.     return $ans
  756. }
  757.  
  758. #================================================================================
  759. proc quoteChar {} {
  760.     message "Literal keystroke to be inserted:"
  761.     insertText [getChar]
  762. }
  763. #===============================================================================
  764.  
  765. proc saveACopyAs {} {
  766.     if {[file exists [set nm [car [winNames -f]]]]} {
  767.         set nm2 [putfile "Save a copy as:" [file tail $nm]]
  768.         cp $nm $nm2
  769.     }
  770. }
  771. #===============================================================================
  772. proc removeDups {l} {
  773.     foreach f $l {
  774.         set silly($f) 1
  775.     }
  776.     if {[info exists silly]} {
  777.         return [array names silly]
  778.     }
  779. }
  780.             
  781.  
  782. #===============================================================================
  783.  
  784. proc printLeftHeader {pg} {
  785.     global printHeader printHeaderTime printHeaderFullPath
  786.     
  787.     if {!$printHeader} return ""
  788.     
  789.     if {$printHeaderFullPath} {
  790.         set text [car [winNames -f]]
  791.     } else {
  792.         set text [lindex [winNames] 0]
  793.     }
  794.     
  795.     if {$printHeaderTime} {
  796.         append text "      [join [mtime [now] short]]"
  797.     }
  798. }
  799.  
  800. proc printRightHeader {pg} {
  801.     return "Page $pg"
  802. }
  803.  
  804. #===============================================================================
  805.  
  806. proc toggleNumLock {} {
  807.     global numLock modifiedVars
  808.     
  809.     set numLock [expr -1 * ($numLock - 1)]
  810.     lappend modifiedVars numLock
  811. }
  812.  
  813. #===============================================================================
  814.  
  815. proc register {} {
  816.     global HOME
  817. #    edit -r "$HOME:Help:Registering"
  818.     launch -f "$HOME:Register"
  819. }
  820.  
  821. #===============================================================================
  822. # Useful for -command flag of 'lsort'.
  823. proc sortByTail {one two} {
  824.     string compare [file tail $one] [file tail $two]
  825. }
  826.  
  827.  
  828. #===============================================================================
  829.  
  830. proc cmdDoubleClick {{from -1} {to -1} {shift 0} {option 0} {control 0}} {
  831.     global mode alphaLite
  832.     
  833.     if {!$alphaLite && [string length [set whe [expandURL]]]} {
  834.         sendUrl [getSelect]
  835.     } else {
  836.         if {$from < 0} {
  837.             set from [getPos]
  838.             set to [selEnd]
  839.             if {$from == $to} {
  840.                 hiliteWord
  841.                 set from [getPos]
  842.                 set to [selEnd]
  843.             }
  844.         }
  845.         
  846.         if {[string length [info commands ${mode}DblClick]]} {
  847.             if {[llength [info args ${mode}DblClick]] == 2} {
  848.                 ${mode}DblClick $from $to
  849.             } else {
  850.                 ${mode}DblClick $from $to $shift $option $control
  851.             }
  852.         } else {
  853.             message "No docs"
  854.         }
  855.     }    
  856. }
  857.  
  858. #===============================================================================
  859.  
  860.  
  861. proc editMark {fname mname args} {
  862.     if {[set pos [lsearch [winNames -f] "*$fname*"]] >= 0}  {
  863.         bringToFront [lindex [winNames -f] $pos]
  864.     } else {
  865.         if {[lsearch $args {-r}] >= 0} {
  866.             edit -r "$fname"
  867.         } else {
  868.             edit "$fname"
  869.         }
  870.     }
  871.     if {[lsearch [getNamedMarks -n] $mname] < 0} {
  872.         global    mode
  873.         ${mode}MarkFile
  874.     } 
  875.     gotoMark $mname
  876. }
  877.  
  878.  
  879. proc winDirty {} {
  880.     getWinInfo arr
  881.     return $arr(dirty)
  882. }
  883.  
  884.  
  885. #===============================================================================
  886.  
  887. proc lreverse {l} {
  888.     if {[llength $l] > 1} {
  889.         set first [lindex $l 0]
  890.         set l [lreverse [lrange $l 1 end]]
  891.         lappend l $first
  892.     }
  893.     return $l
  894. }
  895.  
  896.     
  897. #===============================================================================
  898.  
  899.  
  900. set {patternLibrary(Pascal to C Comments)}      { {¥{([^¥}]*)¥}}    {/* ¥1 */}     }
  901. set {patternLibrary(C++ to C Comments)}            { {//(.*)}            {/* ¥1 */}     }
  902. set {patternLibrary(Space Runs to Tabs)}        { { +}                {¥t}         }
  903.  
  904.  
  905.  
  906. proc getPatternLibrary {} {
  907.     global patternLibrary
  908.     
  909.     foreach nm [array names patternLibrary] {
  910.         lappend nms [concat [list $nm] $patternLibrary($nm)]
  911.     }
  912.     return $nms
  913. }
  914.  
  915. proc rememberPatternHook {search replace} {
  916.     global patternLibrary
  917.     if {[catch {set name [prompt "New pattern's name?" ""]}]} {
  918.         return ""
  919.     }
  920.     addArrDef patternLibrary $name [list $search $replace]
  921.     set patternLibrary($name) [list $search $replace]
  922.     return $name
  923. }
  924.  
  925. proc deletePatternHook {} {
  926.     global patternLibrary
  927.     
  928.     
  929.     set temp [list prompt "Delete which pattern?" [lindex [array names patternLibrary] 0] "Pats:"]
  930.     set name [eval [concat $temp [array names patternLibrary]]]
  931.     removeArrDef patternLibrary $name
  932.     unset patternLibrary($name)
  933. }
  934.  
  935. #===============================================================================
  936. # Support for Peter Gontier's 'ClickWarrior' (Doesn't work for 68k).
  937. #===============================================================================
  938.  
  939. eventHandler ALFA CWOF clickHandler
  940.  
  941. proc clickHandler {msg} {
  942.     global HOME ALPHA CODEWarrior CWCLASS
  943.     switchTo $ALPHA
  944.     checkCw
  945.     if {[regexp {メ(.*)モ.*ヌ.*ネ.*ヌ(.*)ネ.*ヌ(.*)ネ} $msg dummy fname find sind]} {
  946.         set res [AEBuild -t 500000 -r $CODEWarrior $CWCLASS GFil "----" "long(ヌ0000$findネ)" Segm "long($sind)"]
  947.         if {[regexp {FTxt} $res]} {
  948.             regexp {ヌ(.*)ネ} $res dummy spec
  949.             set f [specToPathName $spec]
  950.             edit $f
  951.         }
  952.     }
  953. }
  954.  
  955. #===============================================================================
  956. proc quickFind {} {isearch}
  957. proc reverseQuickFind {} {rsearch}
  958.  
  959. proc pushPosition {} {pushMark}
  960. proc popPosition {} {popMark}
  961. #===============================================================================
  962. proc literalChar {} {
  963.     return [expr {[lookAt [expr [getPos] - 1]] == "¥¥"}]
  964. }
  965. proc isSelection {} {
  966.     return [string length [getSelect]]
  967. }
  968.  
  969. proc findPatJustBefore { findpat pat {pos ""} {matchw ""} } {
  970.     if { $pos == "" } {set pos [getPos] }
  971.     if { $matchw != "" } { upvar  $matchw word }
  972.     if { ![catch {search -s -f 0 -r 1 "$findpat" $pos} res] } {
  973.         if { [regexp "$pat" [getText [lindex $res 0] $pos] dum word] } {
  974.             return [lindex $res 0]
  975.         }
  976.     }
  977.     return
  978. }
  979.  
  980. #===============================================================================
  981. proc mkdir {dir} {
  982.     oldMkdir [list $dir]
  983. }
  984.  
  985. proc rmdir {dir} {
  986.     oldRmdir [list $dir]
  987. }
  988.  
  989. #===============================================================================
  990. proc textToAlpha {{dir ""}} {
  991.     set num 0
  992.     if {![string length $dir]} {
  993.         set dir [get_directory -p "Creators to 'ALFA':"]
  994.     }
  995.  
  996.     if {![catch {glob "$dir:*"} files]} {
  997.         foreach f $files {
  998.             if {[file isfile $f] && ([getFileType $f] == "TEXT") && ([getFileSig $f] != "ALFA")} {
  999.                 message $f
  1000.                 setFileInfo $f creator ALFA
  1001.                 incr num
  1002.             } elseif {[file isdir $f]} {
  1003.                 incr num [textToAlpha $f]
  1004.             }
  1005.         }
  1006.     }
  1007.     message "Converted $num files"
  1008.     return $num
  1009. }
  1010.  
  1011.  
  1012. #===============================================================================
  1013.  
  1014. proc briefThing {} {
  1015.     global lastBrief
  1016.     getWinInfo arr
  1017.     set curr $arr(currline)
  1018.     set where [posToRowCol [getPos]]
  1019.     set row [car $where]
  1020.     set col [cadr $where]
  1021.     
  1022.     if {$col} {
  1023.         set lastBrief [getPos]
  1024.         goto [lineStart [getPos]]
  1025.     } elseif {$curr != $row} {
  1026.         goto [rowColToPos $curr 0]
  1027.     } elseif {[getPos]} {
  1028.         goto 0
  1029.     } else {
  1030.         goto $lastBrief
  1031.     }
  1032. }
  1033.  
  1034. ########################################
  1035. #                                       #
  1036. #    A few random lisp'ish functions.   #
  1037. #                                       #
  1038. ########################################
  1039.  
  1040. proc car {l} {lindex $l 0}
  1041. proc cadr {l} {lindex $l 1}
  1042. proc caddr {l} {lindex $l 2}
  1043. proc cadddr {l} {lindex $l 3}
  1044. proc caddddr {l} {lindex $l 4}
  1045. proc cdr {l} {lrange $l 1 end}
  1046. proc cddr {l} {lrange $l 2 end}
  1047. proc cons {e l} {concat [list $e] $l}
  1048. proc mapcar args {return [eval map $args]}
  1049.  
  1050. proc map {func l} {
  1051.     set out {}
  1052.     foreach el $l {
  1053.         lappend out [eval $func [list $el]]
  1054.     }
  1055.     return $out
  1056. }
  1057.  
  1058.  
  1059. #===============================================================================
  1060.  
  1061. proc deconstruct {} {
  1062.     global HOME 
  1063.     
  1064.     set files {}
  1065.     if {![catch {glob "$HOME:Tcl:Modes:*Mode.tcl"} modes]} {
  1066.         set files $modes
  1067.     }
  1068.     if {![catch {glob "$HOME:Tcl:Menus:*Menu.tcl"} menus]} {
  1069.         set files [concat $files $menus]
  1070.     }
  1071.     
  1072.     foreach f $files {
  1073.         regexp {.*:(.*)M.*.tcl} $f dummy it
  1074.         set theFiles($it) $f
  1075.         lappend tails $it
  1076.     }
  1077.  
  1078.     set res [listpick -p "Permanently remove which modes and menus?" -l [lsort -ignore $tails]]
  1079.     
  1080.     if {[llength $res] && ([askyesno "Are you absolutely sure?"] == "yes")} {
  1081.         foreach tag $res {
  1082.             set name $theFiles($tag)
  1083.             regexp {(.*)M.*.tcl} $name dummy prefix
  1084.             foreach f [glob "${prefix}*.tcl"] {
  1085.                 lappend rfiles $f
  1086.             }
  1087.  
  1088.             set tag [file tail $tag]
  1089.             if {$tag == "perl"} {
  1090.                 catch {rm $HOME:Help:*Perl*}
  1091.             } elseif {$tag == "latex"} {
  1092.                 catch {rm $HOME:Help:LaTeX*}
  1093.             } elseif {$tag == "bibtex"} {
  1094.                 catch {rm $HOME:Help:Bib*}
  1095.             } elseif {$tag == "html"} {
  1096.                 catch {rm $HOME:Help:HTML*}
  1097.             }
  1098.         }
  1099.  
  1100.         foreach f $rfiles {
  1101.             catch {rm $f}
  1102.         }
  1103.  
  1104.         foreach dir [list "$HOME:Tools" "$HOME:Tcl:ElectricAlias" "$HOME:Tcl:UserCode" "$HOME:Help"] {
  1105.             if {[file exists $dir] && ([askyesno "Remove '$dir'?"] == "yes")} {
  1106.                 if {[catch {recursiveRm $dir}]} {
  1107.                     alertnote "Problem removing '$dir'."
  1108.                 }
  1109.             }
  1110.         }
  1111.         
  1112.         rebuildTclIndices
  1113.  
  1114.         alertnote "You must now restart Alpha..."
  1115.         quit
  1116.     }
  1117. }
  1118.  
  1119. proc recursiveRm dir {
  1120.     if {![catch {glob $dir:*} files]} {
  1121.         foreach f $files {
  1122.             if {[file isdir $f]} {
  1123.                 recursiveRm $f
  1124.             } else {
  1125.                 rm $f
  1126.             }
  1127.         }
  1128.     }
  1129.     rmdir $dir
  1130. }
  1131.  
  1132. ###########################################################################
  1133. #  better-cp-mv.tcl  -- modification of your routines, by Mark Nagata
  1134. #  for Alpha 5.72,  1/04/94
  1135. ###########################################################################
  1136. proc cp args {
  1137.     if {[set len [llength $args]] < 2} {
  1138.         error "usage: cp <file1> <file2>¥r       cp <file1> .... <dir>"
  1139.     }
  1140.     set len [expr $len-1]
  1141.     set dir [lindex $args $len]
  1142.     if {![regexp {:} $dir] && $dir != ""} {
  1143.         set dir ":$dir"
  1144.     }
  1145.     if {[regexp {:$} $dir]} {
  1146.         set dir [string trimright $dir {:}]
  1147.     }
  1148.     set args [lreplace $args $len $len]
  1149.     set files {}
  1150.     foreach arg $args {
  1151.         append files " " [glob $arg]
  1152.     }
  1153.     set report ""
  1154.     if {[llength $files] == 1} {
  1155.         set f [lindex $files 0]
  1156.         if {[file exists $dir]} {
  1157.             set targ $dir:[file tail $f]
  1158.             append report $f¥ ->¥ $targ ¥r 
  1159.             copyFile $f $targ
  1160.         } else {
  1161.             append report $f¥ ->¥ $dir ¥r
  1162.             copyFile $f $dir
  1163.         }
  1164.     } else {
  1165.         foreach f $files {
  1166.             message [file tail $f]
  1167.             set targ $dir:[file tail $f]
  1168.             if {[catch {copyFile $f $targ} that]} {
  1169.                 append report "Error copying '$f': $that¥r"
  1170.             } else {
  1171.                 append report $f¥ ->¥ $targ ¥r
  1172.             }
  1173.         }
  1174.     }
  1175.     echo [string trimright $report]
  1176. }
  1177.  
  1178. proc mv args {
  1179.     if {[set len [llength $args]] < 2} {
  1180.         error "usage: mv <file1> <file2>¥r       mv <file1> .... <dir>"
  1181.     }
  1182.     set len [expr $len-1]
  1183.     if {![regexp {.*[^:]} [lindex $args $len] dir]} {
  1184.         set dir [string range [lindex $args $len] 1 end]
  1185.     }
  1186.     if {![regexp {:} $dir] && $dir != ""} {
  1187.         set dir [concat :$dir]}
  1188.     set args [lreplace $args $len $len]
  1189.     set files {}
  1190.     foreach arg $args {
  1191.         append files " " [glob $arg]
  1192.     }
  1193.     set report ""
  1194.     if {[llength $files] == 1} {
  1195.         set f [lindex $files 0]
  1196.         if {[file exists $dir]} {
  1197.             set targ $dir:[file tail $f]
  1198.             append report $f¥ >->¥ $targ ¥r
  1199.             moveFile $f $targ
  1200.         } else {
  1201.             append report $f¥ >->¥ $dir ¥r
  1202.             moveFile $f $dir
  1203.         }
  1204.     } else {
  1205.         foreach f $files {
  1206.             message [file tail $f]
  1207.             set targ $dir:[file tail $f]
  1208.             if {[catch {moveFile $f $targ} that]} {
  1209.                 append report "Error moving '$f': $that¥r"
  1210.             } else {
  1211.                 append report $f¥ >->¥ $targ ¥r
  1212.             }
  1213.         }
  1214.     }
  1215.     echo [string trimright $report]
  1216. }
  1217.  
  1218.  
  1219. proc rm args {
  1220.     set files {}
  1221.     foreach arg $args {
  1222.         append files " " [glob $arg]
  1223.     }
  1224.     foreach f $files {
  1225.         message [file tail $f]
  1226.         removeFile $f
  1227.     }
  1228. }
  1229.  
  1230.  
  1231.